package com.zx.flow.core.execute.eventhandler;

import com.zx.flow.api.config.FlowConfig;
import com.zx.flow.api.config.FlowConfigNode;
import com.zx.flow.api.dict.FlowDict.Event;
import com.zx.flow.api.dict.FlowDict.Status;
import com.zx.flow.api.execute.model.FlowContext;
import com.zx.flow.api.execute.model.FlowNode;
import com.zx.flow.api.execute.request.FlowParamAction;
import com.zx.flow.api.execute.request.FlowParamNodeEntry;
import com.zx.flow.api.execute.request.FlowParamStart;
import com.zx.flow.api.execute.response.FlowResult;
import com.zx.flow.api.util.FlowDataUtil;
import com.zx.flow.api.util.OperatorsUtil;
import com.zx.flow.core.execute.EventHandler;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.springframework.util.CollectionUtils;

/**
 * 事件处理器【流程->启动】
 */
public class EventFlowStartHandler extends EventHandler<FlowParamStart> {

    @Override
    public boolean in(FlowContext flow, FlowParamStart param) {
        // 校验状态
        return flow != null && (Objects.equals(flow.getStatus(), Status.flowNew)
                || Objects.equals(flow.getStatus(), Status.flowSave)
        );
    }

    @Override
    public FlowResult on(FlowContext flow, FlowParamStart param) {
        FlowConfig config = this.getFlowConfig(flow.getFlowConfigCode(), flow.getFlowConfigId());
        List<FlowConfigNode> nodeConfigs = config.getNodes();
        if (CollectionUtils.isEmpty(nodeConfigs)) {
            return FlowResult.fail("没有可以开始的节点", flow);
        }
        FlowConfigNode startNodeConfig = config.getStartNode();
        // node entry 开始节点
        flow = this.execute(new FlowParamNodeEntry(flow.getId(), startNodeConfig.getCode(),
                Arrays.asList(OperatorsUtil.getApply(flow)))).getFlowContext();
        // 获得当前节点
        FlowNode node = FlowDataUtil.getCurrent(flow);
        // node action 直接同意[内部自动进入下个节点]
        flow = this.execute(new FlowParamAction(flow.getId(), node.getId(), Event.nodeApproved.getCode(), "流程开启",
                flow.getApplyAccountCode())).getFlowContext();
        // 保存流程数据
        flow.setStartDateTime(new Date());
        flow.setStatus(Status.flowDoing);
        this.saveFlow(flow);

        // 触发监听
        this.listener(node, Event.flowStart);

        return FlowResult.ok(flow);
    }
}
